
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       sitl_cmdline.c
  * @author     baiyang
  * @date       2022-12-1
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include "sitl_state.h"

#include "sim_multicopter.h"
#include "sim_plane.h"
#include "sim_quadplane.h"

#include <stdio.h>
#include <stdlib.h>
#include <posix/string.h>

#include <sys/time.h>

#include <parameter/param.h>
#include <vehicle/vehicle_type.h>
#include <common/utility/optparse.h>
#include <file_manager/file_manager.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/
enum long_options {
        CMDLINE_GIMBAL = 1,
        CMDLINE_FGVIEW,
        CMDLINE_AUTOTESTDIR,
        CMDLINE_DEFAULTS,
        CMDLINE_UARTA,
        CMDLINE_UARTB,
        CMDLINE_UARTC,
        CMDLINE_UARTD,
        CMDLINE_UARTE,
        CMDLINE_UARTF,
        CMDLINE_UARTG,
        CMDLINE_UARTH,
        CMDLINE_UARTI,
        CMDLINE_UARTJ,
        CMDLINE_RTSCTS,
        CMDLINE_BASE_PORT,
        CMDLINE_RCIN_PORT,
        CMDLINE_SIM_ADDRESS,
        CMDLINE_SIM_PORT_IN,
        CMDLINE_SIM_PORT_OUT,
        CMDLINE_IRLOCK_PORT,
        CMDLINE_START_TIME,
        CMDLINE_SYSID,
        CMDLINE_SLAVE,
#if STORAGE_USE_FLASH
        CMDLINE_SET_STORAGE_FLASH_ENABLED,
#endif
#if STORAGE_USE_POSIX
        CMDLINE_SET_STORAGE_POSIX_ENABLED,
#endif
#if STORAGE_USE_FRAM
        CMDLINE_SET_STORAGE_FRAM_ENABLED,
#endif
};
/*---------------------------------prototype----------------------------------*/
static bool sitlstate_parse_home(const char *home_str, Location *loc, float *yaw_degrees);
static bool sitlstate_lookup_location(const char *home_str, Location *loc, float *yaw_degrees);
static void sitlstate_usage(void);
/*----------------------------------variable----------------------------------*/
const struct optparse_long sim_longopts[] = {
    {"help",            'h', OPTPARSE_NONE},
    {"wipe",            'w', OPTPARSE_NONE},
    {"unhide-groups",   'u', OPTPARSE_NONE},
    {"speedup",         's', OPTPARSE_REQUIRED},
    {"rate",            'r', OPTPARSE_REQUIRED},
    {"console",         'C', OPTPARSE_NONE},
    {"instance",        'I', OPTPARSE_REQUIRED},
    {"param",           'P', OPTPARSE_REQUIRED},
    {"synthetic-clock", 'S', OPTPARSE_NONE},
    {"home",            'O', OPTPARSE_REQUIRED},
    {"model",           'M', OPTPARSE_REQUIRED},
    {"config",          'c', OPTPARSE_REQUIRED},
    {"fg",              'F', OPTPARSE_REQUIRED},
    {"vehicle",         'v', OPTPARSE_REQUIRED},
    {"gimbal",          CMDLINE_GIMBAL, OPTPARSE_NONE},
    {"disable-fgview",  CMDLINE_FGVIEW, OPTPARSE_NONE},
    {"autotest-dir",    CMDLINE_AUTOTESTDIR, OPTPARSE_REQUIRED},
    {"defaults",        CMDLINE_DEFAULTS, OPTPARSE_REQUIRED},
    {"uartA",           CMDLINE_UARTA, OPTPARSE_REQUIRED},
    {"uartB",           CMDLINE_UARTB, OPTPARSE_REQUIRED},
    {"uartC",           CMDLINE_UARTC, OPTPARSE_REQUIRED},
    {"uartD",           CMDLINE_UARTD, OPTPARSE_REQUIRED},
    {"uartE",           CMDLINE_UARTE, OPTPARSE_REQUIRED},
    {"uartF",           CMDLINE_UARTF, OPTPARSE_REQUIRED},
    {"uartG",           CMDLINE_UARTG, OPTPARSE_REQUIRED},
    {"uartH",           CMDLINE_UARTH, OPTPARSE_REQUIRED},
    {"uartI",           CMDLINE_UARTI, OPTPARSE_REQUIRED},
    {"uartJ",           CMDLINE_UARTJ, OPTPARSE_REQUIRED},
    {"rtscts",          CMDLINE_RTSCTS, OPTPARSE_NONE},
    {"base-port",       CMDLINE_BASE_PORT, OPTPARSE_REQUIRED},
    {"rc-in-port",      CMDLINE_RCIN_PORT, OPTPARSE_REQUIRED},
    {"sim-address",     CMDLINE_SIM_ADDRESS, OPTPARSE_REQUIRED},
    {"sim-port-in",     CMDLINE_SIM_PORT_IN, OPTPARSE_REQUIRED},
    {"sim-port-out",    CMDLINE_SIM_PORT_OUT, OPTPARSE_REQUIRED},
    {"irlock-port",     CMDLINE_IRLOCK_PORT, OPTPARSE_REQUIRED},
    {"start-time",      CMDLINE_START_TIME, OPTPARSE_REQUIRED},
    {"sysid",           CMDLINE_SYSID, OPTPARSE_REQUIRED},
    {"slave",           CMDLINE_SLAVE, OPTPARSE_REQUIRED},
#if STORAGE_USE_FLASH
    {"set-storage-flash-enabled", CMDLINE_SET_STORAGE_FLASH_ENABLED, OPTPARSE_REQUIRED},
#endif
#if STORAGE_USE_POSIX
    {"set-storage-posix-enabled", CMDLINE_SET_STORAGE_POSIX_ENABLED, OPTPARSE_REQUIRED},
#endif
#if STORAGE_USE_FRAM
    {"set-storage-fram-enabled",  CMDLINE_SET_STORAGE_FRAM_ENABLED, OPTPARSE_REQUIRED},
#endif
    {0, 0, OPTPARSE_NONE}
};

static const struct {
    const char *name;
    sim_aircraft_t (*constructor)(const char *frame_str);
} model_constructors[] = {
#if 0
    { "xplane",             XPlane::create },
#endif
    { "quadplane",          sim_quadplane_create },
    { "firefly",            sim_quadplane_create },
    { "+",                  sim_multicopter_create },
    { "quad",               sim_multicopter_create },
    { "copter",             sim_multicopter_create },
    { "x",                  sim_multicopter_create },
    { "bfxrev",             sim_multicopter_create },
    { "bfx",                sim_multicopter_create },
    { "djix",               sim_multicopter_create },
    { "cwx",                sim_multicopter_create },
    { "hexa",               sim_multicopter_create },
    { "hexa-cwx",           sim_multicopter_create },
    { "hexa-dji",           sim_multicopter_create },
    { "octa",               sim_multicopter_create },
    { "octa-cwx",           sim_multicopter_create },
    { "octa-dji",           sim_multicopter_create },
    { "octa-quad-cwx",      sim_multicopter_create },
    { "dodeca-hexa",        sim_multicopter_create },
    { "tri",                sim_multicopter_create },
    { "y6",                 sim_multicopter_create },
    { "deca",               sim_multicopter_create },
    { "deca-cwx",           sim_multicopter_create },
    { "plane",              sim_plane_create },
#if 0
    { "heli",               Helicopter::create },
    { "heli-dual",          Helicopter::create },
    { "heli-compound",      Helicopter::create },
    { "heli-blade360",         Helicopter::create },
    { "singlecopter",       SingleCopter::create },
    { "coaxcopter",         SingleCopter::create },
    { "rover",              SimRover::create },
    { "balancebot",         BalanceBot::create },
    { "sailboat",           Sailboat::create },
    { "motorboat",          MotorBoat::create },
    { "crrcsim",            CRRCSim::create },
    { "jsbsim",             JSBSim::create },
    { "flightaxis",         FlightAxis::create },
    { "gazebo",             Gazebo::create },
    { "last_letter",        last_letter::create },
    { "tracker",            Tracker::create },
    { "balloon",            Balloon::create },
    { "calibration",        Calibration::create },
    { "vectored",           Submarine::create },
    { "vectored_6dof",      Submarine::create },
    { "silentwings",        SilentWings::create },
    { "morse",              Morse::create },
    { "airsim",             AirSim::create},
    { "scrimmage",          Scrimmage::create },
    { "webots",             Webots::create },
    { "JSON",               JSON::create },
    { "blimp",              Blimp::create },
#endif
};

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
bool sitlstate_parse_command_line(sitl_state_t sitl, int argc, char * const argv[])
{
    float speedup = 1.0f;
    sitl->_instance = 0;
    sitl->_synthetic_clock_mode = false;
    // default to CMAC
    const char *home_str = NULL;
    const char *model_str = NULL;
    const char *vehicle_type_str = NULL;
    sitl->_use_fg_view = true;
    char *autotest_dir = NULL;
    sitl->_fg_address = "127.0.0.1";
    const char* config = "";

    const int BASE_PORT = 5760;
    const int RCIN_PORT = 5501;
    const int FG_VIEW_PORT = 5503;
    sitl->_base_port = BASE_PORT;
    sitl->_udp_port_offset = 0;
    sitl->_rcin_port = RCIN_PORT;
    sitl->_fg_view_port = FG_VIEW_PORT;

    const int SIM_IN_PORT = 9003;
    const int SIM_OUT_PORT = 9002;
    const int IRLOCK_PORT = 9005;
    const char * simulator_address = "127.0.0.1";
    uint16_t simulator_port_in = SIM_IN_PORT;
    uint16_t simulator_port_out = SIM_OUT_PORT;
    sitl->_irlock_port = IRLOCK_PORT;

    // Set default start time to the real system time.
    // This will be overwritten if argument provided.
    static struct timeval first_tv;
    gettimeofday(&first_tv, NULL);
    time_t start_time_UTC = first_tv.tv_sec;

    // storage defaults are set here:
    bool storage_posix_enabled = true;
    bool storage_flash_enabled = false;
    bool storage_fram_enabled = false;
    bool erase_all_storage = false;

#if 0
    if (sprintf(&autotest_dir, SKETCHBOOK "/Tools/autotest") <= 0) {
        AP_HAL::panic("out of memory");
    }
#endif

    bool wiping_storage = false;

    int option;
    struct optparse options;
    optparse_init(&options, (char**)argv);

    while ((option = optparse_long(&options, sim_longopts, NULL)) != -1) {
        switch (option) {
        case 'w':
            erase_all_storage = true;
            break;
        case 'v':
            vehicle_type_str = options.optarg;
            break;
        case 'u':
            //AP_Param::set_hide_disabled_groups(false);
            break;
        case 's': {
            speedup = strtof(options.optarg, NULL);

            param_t* p = param_get_by_full_name("SIM", "SIM_SPEEDUP");
            if (p != NULL) {
                param_set_float(p, speedup);
                printf("Setting SIM_SPEEDUP=%f\n", speedup);
            }
            } break;
        case 'C':
            //HALSITL::UARTDriver::_console = true;
            break;

        case 'I': {
            sitl->_instance = atoi(options.optarg);
            if (sitl->_base_port == BASE_PORT) {
                sitl->_base_port += sitl->_instance * 10;
            }
            if (sitl->_udp_port_offset == 0) {
                sitl->_udp_port_offset += sitl->_instance * 10;
            }
            if (sitl->_rcin_port == RCIN_PORT) {
                sitl->_rcin_port += sitl->_instance * 10;
            }
            if (sitl->_fg_view_port == FG_VIEW_PORT) {
                sitl->_fg_view_port += sitl->_instance * 10;
            }
            if (simulator_port_in == SIM_IN_PORT) {
                simulator_port_in += sitl->_instance * 10;
            }
            if (simulator_port_out == SIM_OUT_PORT) {
                simulator_port_out += sitl->_instance * 10;
            }
            if (sitl->_irlock_port == IRLOCK_PORT) {
                sitl->_irlock_port += sitl->_instance * 10;
            }
        }
        break;
        case 'P':
            //_set_param_default(gopt.optarg);
            break;
        case 'S':
            sitl->_synthetic_clock_mode = true;
            break;
        case 'O':
            home_str = options.optarg;
            break;
        case 'M':
            model_str = options.optarg;
            break;
        case 'c':
            config = options.optarg;
            break;
        case 'F':
            sitl->_fg_address = options.optarg;
            break;
        case CMDLINE_GIMBAL:
            //sitl->enable_gimbal = true;
            break;
        case CMDLINE_FGVIEW:
            sitl->_use_fg_view = false;
            break;
        case CMDLINE_AUTOTESTDIR:
            autotest_dir = strdup(options.optarg);
            break;
        case CMDLINE_DEFAULTS:
            sitl->defaults_path = strdup(options.optarg);
            break;
        case CMDLINE_UARTA:
        case CMDLINE_UARTB:
        case CMDLINE_UARTC:
        case CMDLINE_UARTD:
        case CMDLINE_UARTE:
        case CMDLINE_UARTF:
        case CMDLINE_UARTG:
        case CMDLINE_UARTH:
        case CMDLINE_UARTI:
        case CMDLINE_UARTJ:
            sitl->_uart_path[option - CMDLINE_UARTA] = options.optarg;
            break;
        case CMDLINE_RTSCTS:
            sitl->_use_rtscts = true;
            break;
        case CMDLINE_BASE_PORT:
            sitl->_base_port = atoi(options.optarg);
            break;
        case CMDLINE_RCIN_PORT:
            sitl->_rcin_port = atoi(options.optarg);
            break;
        case CMDLINE_SIM_ADDRESS:
            simulator_address = options.optarg;
            break;
        case CMDLINE_SIM_PORT_IN:
            simulator_port_in = atoi(options.optarg);
            break;
        case CMDLINE_SIM_PORT_OUT:
            simulator_port_out = atoi(options.optarg);
            break;
        case CMDLINE_IRLOCK_PORT:
            sitl->_irlock_port = atoi(options.optarg);
            break;
        case CMDLINE_START_TIME:
            start_time_UTC = atoi(options.optarg);
            break;
        case CMDLINE_SYSID: {
            const int32_t sysid = atoi(options.optarg);
            if (sysid < 1 || sysid > 255) {
                printf("You must specify a SYSID greater than 0 and less than 256\n");
                return false;
            }
            param_t* p = param_get_by_name("SYSID_THISMAV");
            if (p != NULL) {
                param_set_float(p, (float)sysid);
                printf("Setting SYSID_THISMAV=%d\n", sysid);
            }
            break;
        }
#if STORAGE_USE_POSIX
        case CMDLINE_SET_STORAGE_POSIX_ENABLED:
            storage_posix_enabled = atoi(options.optarg);
            break;
#endif
#if STORAGE_USE_FLASH
        case CMDLINE_SET_STORAGE_FLASH_ENABLED:
            storage_flash_enabled = atoi(options.optarg);
            break;
#endif
#if STORAGE_USE_FRAM
        case CMDLINE_SET_STORAGE_FRAM_ENABLED:
            storage_fram_enabled = atoi(options.optarg);
            break;
#endif
        case 'h':
            sitlstate_usage();
            return false;
        case CMDLINE_SLAVE: {
#if 0
#if HAL_SIM_JSON_MASTER_ENABLED
            const int32_t slaves = atoi(options.optarg);
            if (slaves > 0) {
                ride_along.init(slaves);
            }
#endif
#endif
            break;
        }
        case '?':
            sitlstate_usage();
            return false;
        default:
            sitlstate_usage();
            return false;
        }
    }

    if (!model_str) {
        printf("You must specify a vehicle model.  Options are:\n");
        for (uint8_t i=0; i < ARRAY_SIZE(model_constructors); i++) {
            printf("  %s\n", model_constructors[i].name);
        }
        // spit this out again as the original message probably just
        // scrolled off the screen:
        printf("You must specify a vehicle model.\n");
        return false;
    }

    if (!vehicle_type_str) {
        printf("You must specify a vehicle type.  Options are:\n");

        printf(" copter\n");
        printf(" plane\n");
        printf(" rover\n");
        printf(" sub\n");
        printf(" blimp\n");

        // spit this out again as the original message probably just
        // scrolled off the screen:
        printf("You must specify a vehicle type.\n");
        return false;
    }

    for (uint8_t i=0; i < ARRAY_SIZE(model_constructors); i++) {
        if (strncasecmp(model_constructors[i].name, model_str, strlen(model_constructors[i].name)) == 0) {
            // printf("Creating model %f,%f,%f,%f at speed %.1f\n", opos.lat, opos.lng, opos.alt, opos.hdg, speedup);
            sitl->sitl_model = model_constructors[i].constructor(model_str);
            if (home_str != NULL) {
                Location home;
                float home_yaw;
                if (strchr(home_str,',') == NULL) {
                    if (!sitlstate_lookup_location(home_str, &home, &home_yaw)) {
                        printf("Failed to find location (%s).  Should be in locations.txt or LAT,LON,ALT,HDG e.g. 37.4003371,-122.0800351,0,353\n", home_str);
                        return false;
                    }
                } else if (!sitlstate_parse_home(home_str, &home, &home_yaw)) {
                    printf("Failed to parse home string (%s).  Should be LAT,LON,ALT,HDG e.g. 37.4003371,-122.0800351,0,353\n", home_str);
                    return false;
                }
                sim_aircraft_set_start_location(sitl->sitl_model, &home, home_yaw);
            }
            sim_aircraft_set_interface_ports(sitl->sitl_model, simulator_address, simulator_port_in, simulator_port_out);
            sim_aircraft_set_speedup(sitl->sitl_model, speedup);
            sim_aircraft_set_instance(sitl->sitl_model, sitl->_instance);
            sim_aircraft_set_autotest_dir(sitl->sitl_model, autotest_dir);
            sim_aircraft_set_config(sitl->sitl_model, config);
            sitl->_synthetic_clock_mode = true;
            break;
        }
    }
    if (sitl->sitl_model == NULL) {
        printf("Vehicle model (%s) not found\n", model_str);
        return false;
    }

    if (storage_posix_enabled && storage_flash_enabled) {
        // this will change in the future!
        printf("Only one of flash or posix storage may be selected\n");
        return false;
    }

    if (sim_get_singleton()) {
        // Set SITL start time.
        sim_get_singleton()->start_time_UTC = start_time_UTC;
    }

#if 0
    if (erase_all_storage) {
        AP_Param::erase_all();
        unlink("flash.dat");
        hal.set_wipe_storage(wiping_storage);
    }
#endif

    if (strcmp(vehicle_type_str, "copter") == 0) {
        sitl->_vehicle = SIM_Copter;
    } else if (strcmp(vehicle_type_str, "rover") == 0) {
        sitl->_vehicle = SIM_Rover;
        // set right default throttle for rover (allowing for reverse)
        sitl->pwm_input[2] = 1500;
    } else if (strcmp(vehicle_type_str, "sub") == 0) {
        sitl->_vehicle = SIM_Sub;
        for(uint8_t i = 0; i < 8; i++) {
            sitl->pwm_input[i] = 1500;
        }
    } else if (strcmp(vehicle_type_str, "blimp") == 0) {
        sitl->_vehicle = SIM_Blimp;
        for(uint8_t i = 0; i < 8; i++) {
            sitl->pwm_input[i] = 1500;
        }
    } else {
        sitl->_vehicle = SIM_Plane;
    }

    sitlstate_sitl_setup(sitl);

    return true;
}

/*
  parse a home string into a location and yaw
 */
static bool sitlstate_parse_home(const char *home_str, Location *loc, float *yaw_degrees)
{
    char *saveptr = NULL;
    char *s = strdup(home_str);
    if (!s) {
        free(s);
        printf("No home string supplied\n");
        return false;
    }
    char *lat_s = strtok_r(s, ",", &saveptr);
    if (!lat_s) {
        free(s);
        printf("Failed to parse latitude\n");
        return false;
    }
    char *lon_s = strtok_r(NULL, ",", &saveptr);
    if (!lon_s) {
        free(s);
        printf("Failed to parse longitude\n");
        return false;
    }
    char *alt_s = strtok_r(NULL, ",", &saveptr);
    if (!alt_s) {
        free(s);
        printf("Failed to parse altitude\n");
        return false;
    }
    char *yaw_s = strtok_r(NULL, ",", &saveptr);
    if (!yaw_s) {
        free(s);
        printf("Failed to parse yaw\n");
        return false;
    }

    location_zero(loc);
    loc->lat = (int32_t)(strtod(lat_s, NULL) * 1.0e7);
    loc->lng = (int32_t)(strtod(lon_s, NULL) * 1.0e7);
    loc->alt = (int32_t)(strtod(alt_s, NULL) * 1.0e2);

    if (loc->lat == 0 && loc->lng == 0) {
        // default to CMAC instead of middle of the ocean. This makes
        // SITL in MissionPlanner a bit more useful
        loc->lat = (int32_t)(-35.363261*1e7);
        loc->lng = (int32_t)(149.165230*1e7);
        loc->alt = 584*100;
    }

    *yaw_degrees = strtof(yaw_s, NULL);
    free(s);

    return true;
}

/*
  lookup a location in locations.txt in ROMFS
 */
static bool sitlstate_lookup_location(const char *home_str, Location *loc, float *yaw_degrees)
{
    const char *locations = "/locations.txt";
    file_data_t fd = fs_load_file(locations);
    if (fd == NULL) {
        printf("Missing %s\n", locations);
        return false;
    }
    char *str = strndup((const char *)fd->data, fd->length);
    if (!str) {
        rt_free((void *)fd->data);
        rt_free(fd);
        return false;
    }
    size_t len = strlen(home_str);
    char *saveptr = NULL;
    for (char *s = strtok_r(str, "\r\n", &saveptr);
         s;
         s=strtok_r(NULL, "\r\n", &saveptr)) {
        if (strncasecmp(s, home_str, len) == 0 && s[len]=='=') {
            bool ok = sitlstate_parse_home(&s[len+1], loc, yaw_degrees);
            rt_free(str);

            rt_free((void *)fd->data);
            rt_free(fd);
            return ok;
        }
    }
    rt_free(str);
    rt_free((void *)fd->data);
    rt_free(fd);
    printf("Failed to find location '%s'\n", home_str);
    return false;
}

static void sitlstate_usage(void)
{
    printf("Options:\n"
           "\t--help|-h                display this help information\n"
           "\t--vehicle|-v type        type, e.g. copter/plane/rover/sub/blimp\n"
           "\t--wipe|-w                wipe eeprom\n"
           "\t--unhide-groups|-u       parameter enumeration ignores AP_PARAM_FLAG_ENABLE\n"
           "\t--speedup|-s SPEEDUP     set simulation speedup\n"
           "\t--rate|-r RATE           set SITL framerate\n"
           "\t--console|-C             use console instead of TCP ports\n"
           "\t--instance|-I N          set instance of SITL (adds 10*instance to all port numbers)\n"
           // "\t--param|-P NAME=VALUE    set some param\n"  CURRENTLY BROKEN!
           "\t--synthetic-clock|-S     set synthetic clock mode\n"
           "\t--home|-O HOME           set start location (lat,lng,alt,yaw) or location name\n"
           "\t--model|-M MODEL         set simulation model\n"
           "\t--config string          set additional simulation config string\n"
           "\t--fg|-F ADDRESS          set Flight Gear view address, defaults to 127.0.0.1\n"
           "\t--disable-fgview         disable Flight Gear view\n"
           "\t--gimbal                 enable simulated MAVLink gimbal\n"
           "\t--autotest-dir DIR       set directory for additional files\n"
           "\t--defaults path          set path to defaults file\n"
           "\t--uartA device           set device string for UARTA\n"
           "\t--uartB device           set device string for UARTB\n"
           "\t--uartC device           set device string for UARTC\n"
           "\t--uartD device           set device string for UARTD\n"
           "\t--uartE device           set device string for UARTE\n"
           "\t--uartF device           set device string for UARTF\n"
           "\t--uartG device           set device string for UARTG\n"
           "\t--uartH device           set device string for UARTH\n"
           "\t--uartI device           set device string for UARTI\n"
           "\t--uartJ device           set device string for UARTJ\n"
           "\t--serial0 device         set device string for SERIAL0\n"
           "\t--serial1 device         set device string for SERIAL1\n"
           "\t--serial2 device         set device string for SERIAL2\n"
           "\t--serial3 device         set device string for SERIAL3\n"
           "\t--serial4 device         set device string for SERIAL4\n"
           "\t--serial5 device         set device string for SERIAL5\n"
           "\t--serial6 device         set device string for SERIAL6\n"
           "\t--serial7 device         set device string for SERIAL7\n"
           "\t--serial8 device         set device string for SERIAL8\n"
           "\t--serial9 device         set device string for SERIAL9\n"
           "\t--rtscts                 enable rtscts on serial ports (default false)\n"
           "\t--base-port PORT         set port num for base port(default 5670) must be before -I option\n"
           "\t--rc-in-port PORT        set port num for rc in\n"
           "\t--sim-address ADDR       set address string for simulator\n"
           "\t--sim-port-in PORT       set port num for simulator in\n"
           "\t--sim-port-out PORT      set port num for simulator out\n"
           "\t--irlock-port PORT       set port num for irlock\n"
           "\t--start-time TIMESTR     set simulation start time in UNIX timestamp\n"
           "\t--sysid ID               set SYSID_THISMAV\n"
           "\t--slave number           set the number of JSON slaves\n"
        );
}

/*------------------------------------test------------------------------------*/


